package com.yifeng.repo.controller.excel.simple.upload;

import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
import com.gomcarter.frameworks.base.exception.CustomException;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.*;

/**
 * Created by daibing on 2022/9/14.
 */
@Slf4j
public class MapDataSyncReadListener extends AnalysisEventListener<Map<Integer, String>> {
    private boolean trace = false;
    private int count = 5000;
    private final Map<Integer, String> headMap = new LinkedHashMap<>();
    private final List<Map<Integer, String>> bodyList = new ArrayList<>();

    public MapDataSyncReadListener() {
    }

    public MapDataSyncReadListener(boolean trace, int count) {
        this.trace = trace;
        this.count = count;
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
        log.info("头数据：{}, currentRowHolder: {}", headMap.toString(), context.readRowHolder().getRowIndex());
        this.headMap.putAll(headMap);
    }

    @Override
    public void invoke(Map<Integer, String> data, AnalysisContext context) {
        bodyList.add(data);
        if (trace && bodyList.size() % count == 0) {
            log.info("map read excel count: {}", bodyList.size());
        }
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        // ignore.
    }

    @Override
    public void onException(Exception exception, AnalysisContext context) throws Exception {
        if (exception instanceof ExcelDataConvertException) {
            ExcelDataConvertException e = (ExcelDataConvertException) exception;
            Field field = e.getExcelContentProperty().getField();
            String msg = String.format("第%d行第%d列格式不正确，Excel列名=%s，读取内容=%s，填充字段=%s, 填充类型=%s",
                    e.getRowIndex() + 1,
                    e.getColumnIndex() + 1,
                    getExcelName(field),
                    e.getCellData().getStringValue(),
                    field.getName(),
                    field.getType().getName());
            throw new CustomException(msg);
        }
        throw exception;
    }

    public List<Map<Integer, String>> getBodyList() {
        return bodyList;
    }

    public List<Map<String, String>> getMappingBodyList() {
        if (headMap.isEmpty()) {
            throw new RuntimeException("Not found excel header!");
        }
        List<Map<String, String>> mappingBodyList = new ArrayList<>(bodyList.size());
        for (Map<Integer, String> bodyMap : bodyList) {
            Map<String, String> mappingBodyMap = new LinkedHashMap<>(bodyMap.size());
            for (Map.Entry<Integer, String> entry : bodyMap.entrySet()) {
                mappingBodyMap.put(headMap.get(entry.getKey()), entry.getValue());
            }
            mappingBodyList.add(mappingBodyMap);
        }
        return mappingBodyList;
    }

    private String getExcelName(Field field) {
        ExcelProperty annotation = field.getAnnotation(ExcelProperty.class);
        return annotation != null ? Arrays.toString(annotation.value()) : null;
    }
}
